/**
 * @author Gao Jian
 * @email gaoj@njupt.edu.cn
 * @create date 2021-06-06
 * @desc
 * 关于tiff 数据 不透水面生成建成区
 */

// #define cimg_use_tiff

#include <CImg.h>
#include <cuda_runtime.h>
#include <gdal/gdal.h>
#include <iostream>

using namespace std;
using namespace cimg_library;

int label_bua(unsigned *temp, unsigned char *output, unsigned char *input,
              unsigned resolution, unsigned int nw, unsigned int nh);
void PrintDeviceInfo();

int main(int argc, char **argv) {
  const char *fi = cimg_option("-f", (char *)(NULL), "TiFF File Name");
  const char disp = cimg_option("-dis", 0, "Visualize data");
  const unsigned resl = cimg_option("-r", 0, "resolution (meter).");
  const unsigned verbose = cimg_option("-v", 0, "verbose.");
  const unsigned device_id = cimg_option("-d", 0, "device ID.");

  int deviceCount;
  cudaGetDeviceCount(&deviceCount);

  if (verbose) {
    PrintDeviceInfo();
    printf("使用GPU设备: %d.\n", device_id);
  }
  if (device_id >= deviceCount) {
    if (verbose)
      cout << "错误的设备ID " << device_id << ", 应小于 " << deviceCount
           << "!!!" << endl;
    return -1;
  }
  cudaSetDevice(device_id);

  if (!fi)
    return -1;

  // =========================================================================
  GDALDatasetH hDataset;
  GDALAllRegister();
  hDataset = GDALOpen(fi, GA_Update);
  if (hDataset == NULL) {
    return -1;
  }

  double adfGeoTransform[6];

  GDALGetGeoTransform(hDataset, adfGeoTransform);
  unsigned resolution = resl;
  double arc = 6378245. * 3.14159265358 * 2 / 360;
  if (resl == 0) {
    if (strstr(GDALGetProjectionRef(hDataset), "degree"))
      resolution =
          unsigned((adfGeoTransform[1] - adfGeoTransform[5]) / 2 * arc + 0.5);
    else
      resolution =
          unsigned((adfGeoTransform[1] - adfGeoTransform[5]) / 2 + 0.5);
  }

  GDALRasterBandH hBand;
  // int nw, nh;
  hBand = GDALGetRasterBand(hDataset, 1);
  int nw = GDALGetRasterBandXSize(hBand);
  int nh = GDALGetRasterBandYSize(hBand);
  CImg<unsigned char> datain(nw, nh);
  CPLErr error = GDALRasterIO(hBand, GF_Read, 0, 0, nw, nh, datain.data(), nw,
                              nh, GDT_Byte, 0, 0);

  // =========================================================================
  if (verbose)
    printf("========== Labelling Built Up Area (%dm). ==========\n",
           resolution);

  CImg<unsigned char> odat = datain;

  CImg<unsigned char> dataout(nw, nh, 1, 1, 0);
  // CImg<unsigned> temp(nw, nh, 1, 1, 0);
  dataout = datain;

  label_bua(NULL, dataout.data(), datain.data(), resolution, nw, nh);

  // =========================================================================
  error = GDALRasterIO(hBand, GF_Write, 0, 0, nw, nh, dataout.data(), nw, nh,
                       GDT_Byte, 0, 0);

  GDALClose(hDataset);

  // =========================================================================

  if (verbose)
    printf("========================= <<<< Finished. >>>> "
           "=========================\n");
  // if (fo)
  //   dataout.save(fo);

  if (disp)
    (odat, dataout).display("INPUT | OUTPUT");

  return 0;
}
